package
{
	import Connector.Connection;
	
	import Libs.myLib;
	
	import Player.Player;
	
	import Timer.SynTimer;
	
	import alternativa.engine3d.animation.AnimationClip;
	import alternativa.engine3d.animation.AnimationController;
	import alternativa.engine3d.animation.AnimationSwitcher;
	import alternativa.engine3d.collisions.EllipsoidCollider;
	import alternativa.engine3d.controllers.SimpleObjectController;
	import alternativa.engine3d.core.Camera3D;
	import alternativa.engine3d.core.Object3D;
	import alternativa.engine3d.core.Resource;
	import alternativa.engine3d.core.View;
	import alternativa.engine3d.loaders.ParserCollada;
	import alternativa.engine3d.materials.FillMaterial;
	import alternativa.engine3d.materials.TextureMaterial;
	import alternativa.engine3d.objects.Skin;
	import alternativa.engine3d.objects.WireFrame;
	import alternativa.engine3d.primitives.Box;
	import alternativa.engine3d.primitives.Plane;
	import alternativa.engine3d.resources.BitmapTextureResource;
	
	import com.hexagonstar.util.debug.Debug;
	
	import flash.display.Sprite;
	import flash.display.Stage3D;
	import flash.display.StageAlign;
	import flash.display.StageDisplayState;
	import flash.display.StageScaleMode;
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.events.FullScreenEvent;
	import flash.events.KeyboardEvent;
	import flash.geom.Vector3D;
	import flash.ui.Keyboard;
	import flash.utils.getTimer;
	
	[SWF(backgroundColor="#000000", frameRate="60", width="800", height="600")]
	
	
	public class Alternativa2 extends Sprite
	{
		private var rootContainer:Object3D = new Object3D();
		private var camera:Camera3D;
		private var stage3D:Stage3D;
		private var hero:Player;
		//private var hero:Skin;
		private var animationController:AnimationController = new AnimationController();
		private var animationSwitcher:AnimationSwitcher = new AnimationSwitcher();
		private var idle:AnimationClip;
		private var run:AnimationClip;
		
		private var ground:Plane = new Plane(10000,10000);
		private var theWall:Object3D;
		private var hero_height:int = 160;
		private var cameraDistance:int = 2000;
		
		private var cameraPos:int = 1;
		private var speed:Number = 0
		private var steering:Number = 0
		private var collider:EllipsoidCollider = new EllipsoidCollider(40, 40, 5);
		private var con:Connection;
		private var gravity:Number = 10;
		private var fallSpeed:Number = 0;
		private var lastTime:int;
		private var timeScale:Number = 0.7;
		
		public var isForward:Boolean = false;
		public var isBack:Boolean = false;
		public var isLeft:Boolean = false;
		public var isRight:Boolean = false;
		public var isRun:Boolean = false;
		public var isJump:Boolean = false;
		
		private var pUserName:String = "TEST1";
		private var pRole:String = "police";
		private var synTimer:SynTimer;
		public function Alternativa2()
		{
			Debug.monitor(stage);
			Debug.trace("Connect to Debugger");
			//con =  new Connection(pUserName);
			//con.login(pUserName,pRole);
			synTimer = new SynTimer();
			
			stage.align = StageAlign.TOP_LEFT;
			stage.scaleMode = StageScaleMode.NO_SCALE;
			
			camera = new Camera3D(10, 10000);
			camera.view = new View(stage.stageWidth, stage.stageHeight);
			camera.view.antiAlias = 4;
			camera.view.hideLogo();
			
			
			addChild(camera.view);
			addChild(camera.diagram);
			
			camera.rotationX = deg2rad(70);
			camera.rotationZ = Math.PI;

			camera.z = - hero_height*3;
			//camera.x = 00;
			//camera.y = 00;
			
			myLib.log(camera);
			
			rootContainer.addChild(camera);
			// cameraController
			/*cameraController = new SimpleObjectController(stage,camera,300,2);

			cameraController.unbindKey(Keyboard.W);
			cameraController.unbindKey(Keyboard.A);
			cameraController.unbindKey(Keyboard.S);
			cameraController.unbindKey(Keyboard.D);*/
			
			makeAxes();
			
			generateRandomMapOfCubes();
			
			createHero();
			
			
			stage3D = stage.stage3Ds[0];
			stage3D.addEventListener(Event.CONTEXT3D_CREATE, onContextCreate);
			stage3D.requestContext3D();
		}
		private function createHero():void{
			
			hero = new Player(pUserName,pRole);
			
			hero.z = -500;
			
			rootContainer.addChild(hero);
			Debug.trace("Hero = " + hero.x + "," + hero.y + "," + hero.z);
		}
		public function followCarWithCamera():void{
			
			var targetX:Number = hero.x + Math.sin(hero.rotationZ)*cameraDistance;
			var targetY:Number = hero.y - Math.cos(hero.rotationZ)*cameraDistance;
			var targetZRotation:Number = hero.rotationZ+Math.PI;
			
			camera.x -= (camera.x - targetX)*.2;
			camera.y -= (camera.y - targetY)*.2;
			//camera.z = (hero.z - hero_height) - hero_height*cameraPos;
			
			camera.rotationZ -= (camera.rotationZ - targetZRotation)*.2;
			
		} 
		private function onContextCreate(e:Event):void {
			for each (var resource:Resource in rootContainer.getResources(true)) {
				resource.upload(stage3D.context3D);
			}
					
			stage.addEventListener(Event.ENTER_FRAME, onEnterFrame);
			stage.addEventListener(Event.RESIZE, onResize);
			stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown);
			stage.addEventListener(KeyboardEvent.KEY_UP, onKeyUp);
			stage.addEventListener(FullScreenEvent.FULL_SCREEN,onFullView);
			lastTime = getTimer();
			
		}
		private function onFullView(event:Event) : void
		{
			
			stage.removeEventListener(FullScreenEvent.FULL_SCREEN, this.onFullView);
			
		}
		private function makeAxes():void {
			var axisX:WireFrame = WireFrame.createLinesList(Vector.<Vector3D>([new Vector3D(0, 0, 0), new Vector3D(300, 0, 0),  new Vector3D(300, 0, 0),  new Vector3D(280, 10, 0),  new Vector3D(300, 0, 0),  new Vector3D(280, -10, 0) ]), 0x0000ff, 2);
			var axisY:WireFrame = WireFrame.createLinesList(Vector.<Vector3D>([new Vector3D(0, 0, 0), new Vector3D(0, 300, 0), new Vector3D(0, 300, 0),new Vector3D(0, 280, 10),new Vector3D(0, 300, 0),new Vector3D(0, 280, -10)  ]), 0xff0000, 2);
			var axisZ:WireFrame = WireFrame.createLinesList(Vector.<Vector3D>([new Vector3D(0, 0, 0), new Vector3D(0, 0, 300), new Vector3D(0, 0, 300),new Vector3D(10, 0, 280),new Vector3D(0, 0, 300),new Vector3D(-10, 0, 280) ]), 0x00ff00, 2);
			rootContainer.addChild(axisX);
			rootContainer.addChild(axisY);
			rootContainer.addChild(axisZ);
			
		}
		public function generateRandomMapOfCubes():void{
			theWall = new Object3D();
			//ground.setMaterialToAllSurfaces(new FillMaterial(0xCCCCCC,0.3));
			ground.getSurface(0).material = new FillMaterial(0xCCCCCC,0.3);
			ground.getSurface(1).material = new FillMaterial(0xFFCCFF,0.3);
			rootContainer.addChild(ground);
			
			for(var i:uint = 0;i<30;i++){
				var height:Number = Libs.myLib.rand(1,5) * hero_height;
				var b:Box = new Box(Math.random()*700+200,Math.random()*700+200,height);
				b.setMaterialToAllSurfaces(new FillMaterial(0xCCCCCC,0.5));
				
				b.z = -height/2;
				b.x = 5000-Math.random()*10000;
				b.y = 5000-Math.random()*10000;
				theWall.addChild(b);
			}
			rootContainer.addChild(theWall);
		}

		public function onKeyUp(e:KeyboardEvent):void {
			
			switch(e.keyCode){
				case Keyboard.W: 
					isForward = false;
					break; // W
				case Keyboard.A: 
					isLeft =false;
					break; // A
				case Keyboard.S: 
					isBack = false;
					break; // S
				case Keyboard.D: 
					isRight =false;
					break; // D
				case Keyboard.C:
					changeCameraPos();
					break;
				case Keyboard.SPACE: 
					isJump = false;
					break;
				case Keyboard.F:
					// show full
					if (stage.displayState == StageDisplayState.NORMAL)
					{
						stage.displayState = StageDisplayState.FULL_SCREEN_INTERACTIVE;
					}
					else
					{
						stage.displayState = StageDisplayState.NORMAL;
					}
					onResize();
					break;
			}
		}
		public function onKeyDown(e:KeyboardEvent):void
		{
			var isKeyDown:Boolean = true;
			Debug.trace(e.keyCode);
			switch(e.keyCode){
				case Keyboard.W: 
					isForward=true;
					break; // W
				case Keyboard.A: 
					isLeft =true;
					break; // A
				case Keyboard.S: 
					isBack =true;
					break; // S
				case Keyboard.D: 
					isRight =true;
					break; // D
				case Keyboard.C:
					
					break;
				case Keyboard.SPACE: 
					isJump = true;
					break;
			}
		}
		private function changeCameraPos():void{
			cameraPos = (cameraPos + 1) % 2;
			switch(cameraPos)
			{
				case 0: 
				{
					// can canh
					camera.z = -hero_height;
					//camera.x = hero.x;
					//camera.y = hero.y;
					cameraDistance = 100;
					
					break;
				}
				case 1:
				{
					// Nhin tu xa
					camera.z = - hero_height*2;
					cameraDistance = 800;
					break;
				}
			}
		}
		private function onEnterFrame(e:Event):void {
			
			//Debug.trace(stage.stageWidth + "-" + stage.stageHeight);
			camera.view.height = stage.stageHeight;
			camera.view.width = stage.stageWidth;
			
			var displacement:Vector3D = new Vector3D();
			var time:int = getTimer();
			var deltaTime:Number = timeScale*(time - lastTime)/1000;
			
			lastTime = time;
			
			if (isForward ) {
				speed = 50;
			}
			else if (isBack ) {
				speed = -50;
			}
			else {
				speed = 0;			
			}
			
			if (isLeft) {
				steering += Math.PI/40;
			}
			else if (isRight) {
				steering -= Math.PI/40;
			}

			if (isJump && displacement.z > camera.z){
				displacement.z = -hero_height/2;
			}
			else {
				displacement.z = 0;
			}
			
			hero.rotationZ = -steering
				
			displacement.x = speed*Math.sin(steering);
			displacement.y = speed*Math.cos(steering);
			//displacement.scaleBy(deltaTime*600/displacement.length);
				
			// Fall speed
			fallSpeed += 0.5*gravity;
						
			// toa do foot nhan vat
			var characterCoords:Vector3D = new Vector3D(hero.x, hero.y, hero.z);
			
			// Checking of surface under character foot
			var collisionPoint:Vector3D = new Vector3D();
			var collisionPlane:Vector3D = new Vector3D();

			var onGround:Boolean = collider.getCollision(characterCoords, new Vector3D(0, 0, fallSpeed), collisionPoint, collisionPlane,ground);
			//Debug.trace("Collision onGround = " + onGround );
			//Debug.traceObj(collisionPlane);
			
			if (onGround && collisionPlane.z > 0.5) {
				fallSpeed = 0;
			}
			displacement.z += fallSpeed;
			
			// Collision detection voi doi Tuong tren nen

			var destination:Vector3D = collider.calculateDestination(characterCoords, displacement, theWall);
			//Debug.trace("Collision Destination = " + destination );
			
			// check vi tri vang xa
			if (Math.abs(destination.x - hero.x) > Math.abs(speed) ) destination.x = hero.x + speed;
			hero.x = destination.x;
			if (Math.abs(destination.y - hero.y) > Math.abs(speed) ) destination.y = hero.y + speed;
			hero.y = destination.y;
			if (destination.z > -0.5) destination.z = 0;
			hero.z = destination.z ;
			
			//cameraController.update();
			//box.rotationZ -= 0.01;
			
			followCarWithCamera();
			
			camera.render(stage3D);
		}
		private function onResize(e:Event = null):void {
			// Width and height of view
			
			camera.view.width = stage.stageWidth;
			camera.view.height = stage.stageHeight;
		}
		public function rad2deg(radnum:Number):Number{
			return radnum*180/Math.PI;
		}
		
		public function deg2rad(degnum:Number):Number{
			return degnum*Math.PI/180;
		}
	}
}